FI simulation with a moving point scatterer on a phased array with the USTB built-in Fresnel simulator

In this example we show how to use the built-in fresnel simulator in USTB to generate a Conventional Focused Imaging (single focal depth) dataset for a phased array and a sector scan and how it can be beamformed with USTB. Specifically, in this example, a point scatterer under study moves between acquired frames.

This tutorial assumes familiarity with the contents of the 'CPWC simulation with the USTB built-in Fresnel simulator' tutorial. Please feel free to refer back to that for more details.

by Alfonso Rodriguez-Molares alfonso.r.molares@ntnu.no, Ole Marius Hoel Rindal olemarius@olemarius.net and Arun Asokan Nair anair8@jhu.edu 11.03.2017

Contents

Close all previously opened plots.

close all;

Phantom

The fresnel simulator takes a phantom structure as input. phantom is an Ultrasound File Format (UFF) structure that contains the position of a of a point scatterer(s). USTB's implementation of phantom includes a plot method Below, we only deal with a single point scatterer. We can change N_sca to have multiple point scatterers, and have to add the appropriate additional information below.

N_sca=1;                            % number of scatterers
x_sca=-20e-3;                       % azimuthal position of scatterer(s) [m]
z_sca=30e-3;                        % axial position of scatterer(s) [m]
p=[x_sca zeros(N_sca,1) z_sca];     % matrix of scatterer position vectors
N_frames=5;                         % number of frames
N_beams=128;                        % number of focused beams
alpha=35*pi/180;                    % scatterer direction [rad]
v_mag=0.25;                         % scatterer velocity magnitude [m/s]
v=v_mag*ones(N_sca,1)*[cos(alpha) 0 sin(alpha)]; % scatterer velocity [m/s m/s m/s]
PRF=4000;                           % pulse repetition frequency [Hz]
fig_handle=figure();
for n=1:N_frames*N_beams
    pha(n)=uff.phantom();
    pha(n).sound_speed=1540;            % speed of sound [m/s]
    pha(n).points=[p+v*(n-1)/PRF, ones(N_sca,1)];    % point scatterer position [m]
    pha(n).plot(fig_handle);
end

Probe

The next UFF structure we look at is probe. It contains information about the probe's geometry. USTB's implementation of probe comes with a plot method too. When combined with the previous figure we can see the position of the probe respect to the phantom.

prb=uff.linear_array();
prb.N=64;                   % number of elements
prb.pitch=300e-6;           % probe pitch in azimuth [m]
prb.element_width=270e-6;   % element width [m]
prb.element_height=7000e-6; % element height [m]
prb.plot(fig_handle);

Pulse

We then define the pulse-echo signal which is done here using the fresnel simulator's pulse structure. We could also use 'Field II' for a more accurate model.

pul=uff.pulse();
pul.center_frequency=3e6;       % transducer frequency [MHz]
pul.fractional_bandwidth=0.6;   % fractional bandwidth [unitless]
pul.plot([],'2-way pulse');

Sequence generation

Now, we shall generate our sequence! Keep in mind that the fresnel simulator takes the same sequence definition as the USTB beamformer. In UFF and USTB a sequence is defined as a collection of wave structures.

For our example here, we define a sequence of 128 (= N_beams) focused beams spanning an azimuthal angular range of $[-\frac{35\pi}{180},\frac{35\pi}{180} ]$ radians. The focal depth is set as 40 mm. The wave structure too has a plot method.

azimuth_axis=linspace(-35*pi/180,35*pi/180,N_beams).';  % beam angle vector [rad]
depth=40e-3;                                            % fixed focal depth [m]
seq=uff.wave();
for n=1:N_beams
    seq(n)=uff.wave();
    seq(n).probe=prb;

    seq(n).source=uff.point();
    seq(n).source.azimuth=azimuth_axis(n);
    seq(n).source.distance=depth;

    seq(n).apodization=uff.apodization();
    seq(n).apodization.window=uff.window.tukey50;
    seq(n).apodization.f_number=1.7;
    seq(n).apodization.focus=uff.sector_scan('xyz',seq(n).source.xyz);

    seq(n).sound_speed=pha.sound_speed;

    % show source
    fig_handle=seq(n).source.plot(fig_handle);
end

The Fresnel simulator

Finally, we launch the built-in simulator. The simulator takes in a phantom, pulse, probe and a sequence of wave structures along with the desired sampling frequency, and returns a channel_data UFF structure.

sim=fresnel();

% setting input data
sim.phantom=pha;                % phantom
sim.pulse=pul;                  % transmitted pulse
sim.probe=prb;                  % probe
sim.sequence=seq;               % beam sequence
sim.sampling_frequency=41.6e6;  % sampling frequency [Hz]

% we launch the simulation
channel_data=sim.go();
USTB's Fresnel impulse response simulator (v1.0.7)
---------------------------------------------------------------

Scan

The scan area is defines as a collection of pixels spanning our region of interest. For our example here, we use the sector_scan structure to generate a sector scan. scan too has a useful plot method it can call.

depth_axis=linspace(5e-3,80e-3,256).';
scan=uff.sector_scan('azimuth_axis',azimuth_axis,'depth_axis',depth_axis);

Midprocess

With channel_data and a scan we have all we need to produce an ultrasound image. We now use a USTB structure midprocess, that takes an apodization structure in addition to the channel_data and scan, and returns a beamformed_data.

mid=midprocess.das();
mid.channel_data=channel_data;
mid.scan=scan;
mid.dimension = dimension.both();

mid.transmit_apodization.window = uff.window.scanline;

mid.receive_apodization.window=uff.window.tukey50;
mid.receive_apodization.f_number=1.7;


b_data=mid.go();
USTB General beamformer MEX v1.1.2 .............done!

Plotting the data

The below plot method shows an interactive window in which we can play the multiple frames as a movie.

b_data.plot();